﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Diagnostics;
using System.ComponentModel;

namespace JasLib.Interop.Win32
{
    public static partial class WTSAPI32
    {
        [DllImport(Constants.ModuleNames.WTSAPI, SetLastError = true, EntryPoint = "WTSCloseServer", CharSet = CharSet.Unicode)]
        public static extern void WTSCloseServer([In] HANDLE hServer);

        [DllImport(Constants.ModuleNames.WTSAPI, SetLastError = true, EntryPoint = "WTSEnumerateSessionsW", CharSet = CharSet.Unicode)]
        public static extern bool WTSEnumerateSessions(
            [In] HANDLE hServer,
            [In] uint Reserved,
            [In] uint Version,
            [Out] out UINT_PTR ppSessionInfo,
            [Out] out uint pCount);

        /// <summary>
        /// Safe wrapper for the WTSEnumerateSessions Win32 function that throws an exception on failure.
        /// </summary>
        public static WTS_SESSION_INFO[] WTSEnumerateSessions(HANDLE hServer, uint Reserved = 0, uint Version = 1)
        {
            UINT_PTR pBuffer = UINT_PTR.Zero;
            uint uiCount = 0;

            if (!WTSEnumerateSessions(hServer, Reserved, Version, out pBuffer, out uiCount))
                throw new Win32Exception();

            WTS_SESSION_INFO[] sessions;
            try
            {
                sessions = MarshalHelper.PtrToStructureArray<WTS_SESSION_INFO>(pBuffer, (int)uiCount);
            }
            finally
            {
                WTSFreeMemory(pBuffer);
            }

            return sessions;
        }

        [DllImport(Constants.ModuleNames.WTSAPI, SetLastError = true, EntryPoint = "WTSFreeMemory", CharSet = CharSet.Unicode)]
        public static extern void WTSFreeMemory([In] UINT_PTR pMemory);

        [DllImport(Constants.ModuleNames.WTSAPI, SetLastError = true, EntryPoint = "WTSOpenServerW", CharSet = CharSet.Unicode)]
        public static extern HANDLE WTSOpenServer([In] string pServerName = null);

        [DllImport(Constants.ModuleNames.WTSAPI, SetLastError = true, EntryPoint = "WTSOpenServerExW", CharSet = CharSet.Unicode)]
        public static extern HANDLE WTSOpenServerEx([In] string pServerName = null);

        [DllImport(Constants.ModuleNames.WTSAPI, EntryPoint = "WTSSendMessageW", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Winapi, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool WTSSendMessage(
            [In] HANDLE hServer,
            [In] uint SessionId,
            [In, MarshalAs(UnmanagedType.LPWStr)] string pTitle,
            [In] uint dwTitleLength,
            [In, MarshalAs(UnmanagedType.LPWStr)] string pMessage,
            [In] uint dwMessageLength,
            [In] MessageBoxFlags Style,
            [In] uint Timeout,
            [Out] out uint pResponse,
            [In, MarshalAs(UnmanagedType.Bool)] bool bWait);

        /// <summary>
        /// Convenience wrapper for the Win32 WTSSendMessage function that throws an exception on failure.
        /// </summary>
        public static DialogResultType WTSSendMessage(
            HANDLE hServer,
            uint uiSessionId,
            string strMessage,
            string strTitle = "",
            MessageBoxFlags Style = MessageBoxFlags.MB_OK,
            uint? uiTimeout = null)
        {
            uint uiResponse;
            if (!WTSSendMessage(hServer, uiSessionId, strTitle, (uint)strTitle.Length, strMessage, (uint)strMessage.Length, Style, (uiTimeout ?? 0), out uiResponse, uiTimeout.HasValue))
                throw new Win32Exception();
            return (DialogResultType)(int)uiResponse;
        }
    }
}
